﻿using System;
using System.Management;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
using System.Text.RegularExpressions;
using System.IO;
using System.Diagnostics;
using System.Threading;
using System.Runtime.InteropServices;
using Microsoft.Win32;

namespace SerialportSample
{
 

    public partial class FormMain : Form
    {
        private SerialPort comm = new SerialPort();
        private StringBuilder builder = new StringBuilder();//避免在事件处理方法中反复的创建，定义到外面。
        private long received_count = 0;//接收计数
        private static System.Diagnostics.Process p;
        public const int WM_DEVICE_CHANGE = 0x219;
        public const int DBT_DEVICEARRIVAL = 0x8000;
        public const int DBT_DEVICEREMOVECOMPLETE = 0x8004;

        //因为耗时太长，定义一个下载固件的线程，在线程中处理
        private Thread DownloadHexThread;
        //定义一个标志，用于判断线程是否结束
        private bool bDownloadHexThreadOver = true;
        private string HexFileName = null;
        private string PortName = null;
        private string HexSize = null;
        protected override void DefWndProc(ref System.Windows.Forms.Message m)
        {
            if (m.Msg == WM_DEVICE_CHANGE)        // 捕获USB设备的拔出消息WM_DEVICECHANGE
            {
                string sc = null;
                //Thread.Sleep(300);    //lds330
                sc = LocateComPort();
                if (m.WParam.ToInt32() == DBT_DEVICEREMOVECOMPLETE)
                {
                    if (sc == null)
                    {
                        buttonOpenClose.Text = "Scan Dev";
                        comboPortName.Enabled = true;
                        comboPortName.Items.Clear();
                        if (comm.IsOpen)
                        {
                            comm.Close();
                            comm.Dispose();
                        }
                    }
                }
                else if (m.WParam.ToInt32() == DBT_DEVICEARRIVAL)
                {
                    if (sc != null)
                        comboPortName.Items.Add(sc);
                }
            }
            base.DefWndProc(ref m);
        }
        private static string LocateComPort()
        {
            string comPort = null;
            int index = 0;
            foreach (string portName in GetHardName.GetSerialPort())
            {
                comPort = portName;
                if (comPort.IndexOf("Maxim") >= 0)
                {
                    index = comPort.IndexOf("COM");
                    if (index >= 0)
                    {
                        comPort = comPort.Substring(index);
                        comPort = comPort.Substring(0, comPort.Length - 1);
                        SerialPort serialPort = new SerialPort(comPort);
                        SerialPort _tempPort = serialPort;
                        try
                        {
                            _tempPort.Open();
                            System.Threading.Thread.Sleep(10);
                            if (_tempPort.IsOpen)
                            {
                                //MessageBox.Show("Comm Port Found", "Success!");
                                _tempPort.Close();
                                _tempPort.Dispose();
                                return comPort;
                            }

                        }
                        catch (Exception)
                        {
                            MessageBox.Show("No Ports available", "Error!");
                            _tempPort.Dispose();
                        }
                    }
                }
            }

            //RegistryKey ComPortKey = Registry.LocalMachine.OpenSubKey("SYSTEM\\CurrentControlSet\\Enum\\USB\\VID_0B6A&PID_0625");

            //foreach (string subKeyName in ComPortKey.GetSubKeyNames())
            //{
            //    using (RegistryKey tempKey = ComPortKey.OpenSubKey(subKeyName))
            //    {
            //        foreach (string valueName in tempKey.GetValueNames())
            //        {
            //            if (tempKey.GetValue(valueName).ToString().IndexOf("Maxim") > -1)
            //            {
            //                int index = tempKey.GetValue(valueName).ToString().IndexOf("COM");
            //                if (index > -1)
            //                {
            //                    string comPort = tempKey.GetValue(valueName).ToString().Substring(index);
            //                    comPort = comPort.Substring(0, comPort.Length - 1);
            //                    SerialPort _tempPort = new SerialPort(comPort);
            //                    try
            //                    {
            //                        _tempPort.Open();
            //                        System.Threading.Thread.Sleep(10);
            //                        if (_tempPort.IsOpen)
            //                        {
            //                            //MessageBox.Show("Comm Port Found", "Success!");
            //                            _tempPort.Close();
            //                            _tempPort.Dispose();
            //                            return comPort;
            //                        }

            //                    }
            //                    catch (Exception)
            //                    {
            //                        //MessageBox.Show("No Ports available", "Error!");
            //                        _tempPort.Dispose();
            //                    }
            //                }
            //            }
            //        }
            //    }
            //}
            return null;
        }
        
        
        public FormMain( )
        {
            InitializeComponent();
        }

        //窗体初始化
        private void Form1_Load(object sender, EventArgs e)
        {
            //初始化下拉串口名称列表框
            //string[] ports = MyPort;
            string sc = null;
            sc = LocateComPort();
            if (sc == null)
                this.txGet.AppendText("\r\nNo hardware found\r\n");
            else
                comboPortName.Items.Add(sc);
            comboPortName.SelectedIndex = comboPortName.Items.Count > 0 ? 0 : -1;
            comboBoxDUTSize.SelectedIndex = comboBoxDUTSize.Items.IndexOf("128K");

            //初始化SerialPort对象
            comm.NewLine = "\r\n";
            comm.RtsEnable = true;//根据实际情况吧。

            //添加事件注册
            comm.DataReceived += comm_DataReceived;
            
        }


        void comm_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            int n = comm.BytesToRead;//先记录下来，避免某种原因，人为的原因，操作几次之间时间长，缓存不一致
            if (n == 0)
                return;
            byte[] buf = new byte[n];//声明一个临时数组存储当前来的串口数据
            received_count += n;//增加接收计数
            comm.Read(buf, 0, n);//读取缓冲数据
            builder.Clear();//清除字符串构造器的内容
            byte[] buf1 = new byte[50];
            //因为要访问ui资源，所以需要使用invoke方式同步ui。
            this.Invoke((EventHandler)(delegate
            {
                switch (buf[0])
                {
                    default:

                        //判断是否是显示为16禁止
                        if (checkBoxHexView.Checked)
                        {
                            //依次的拼接出16进制字符串
                            foreach (byte b in buf)
                            {
                                builder.Append(b.ToString("X2") + " ");
                            }
                        }
                        else
                        {
                            //直接按ASCII规则转换成字符串  影响速度.
                            // builder.Append(Encoding.ASCII.GetString(buf));
                        }
                        break;

                }
            }));
        }

        private void buttonOpenClose_Click(object sender, EventArgs e)
        {
            string sc = null;
            sc = LocateComPort();
            comboPortName.Items.Clear();
            if (sc == null)
                this.txGet.AppendText("\r\nNo hardware found\r\n");
            else
                comboPortName.Items.Add(sc);
            comboPortName.SelectedIndex = comboPortName.Items.Count > 0 ? 0 : -1;
            comboBoxDUTSize.SelectedIndex = comboBoxDUTSize.Items.IndexOf("128K");

            //初始化SerialPort对象
            comm.NewLine = "\r\n";
            comm.RtsEnable = true;//根据实际情况吧。

            //添加事件注册
            comm.DataReceived += comm_DataReceived;
        }
        
        private void proc_execute(string aug)
        {
            ProcessStartInfo start = new ProcessStartInfo(Application.StartupPath + "\\inc\\TFP3.exe");
            start.Arguments = aug;//设置命令参数
            start.CreateNoWindow = true;//不显示dos命令行窗口
            start.RedirectStandardOutput = true;//
            start.RedirectStandardInput = true;//
            start.UseShellExecute = false;//是否指定操作系统外壳进程启动程序
            //Process p = null;
            StreamReader reader = null;
            try
            {
                p = Process.Start(start);
                reader = p.StandardOutput;//截取输出流
                string line = reader.ReadLine();//每次读取一行
                //this.txGet.AppendText(".");
                while (!reader.EndOfStream)
                {
                    if (line.Length > 0)
                    {
                        Invoke
                        (new EventHandler
                        (delegate
                        {
                            txGet.AppendText(line + "\r\n");
                        }
                        )
                        );
                    }

                    line = reader.ReadLine();
                    if (backgroundWorker1.CancellationPending)
                    {
                        break;
                    }
                }


            }
            //catch (Exception ex)
            //{
            //    this.txGet.AppendText("无效指令\r\n");
            //}
            finally
            {
                try
                {
                    p.Close();//关闭进程
                    reader.Close();//关闭流
                }
                catch { }
            }
        }
        private void buttonSendFile_Click(object sender, EventArgs e)
        {
            if (bDownloadHexThreadOver == true)
            { 
                OpenFileDialog file1 = new OpenFileDialog();
                file1.Filter = "Hex|*.hex|All file|*.*";
                if (file1.ShowDialog() == DialogResult.OK)
                {
                    received_count = 0;
                
                    txGet.AppendText(file1.FileName);
                    txGet.AppendText("\r\n");
                    txGet.AppendText("\r\n");

                    //因为FTP3.EXE只能在英文目录的根目录运行，因此先把hex文件复制到此软件运行的根目录

                    if (CopyFile(file1.FileName, Application.StartupPath, true, out HexFileName) == true)
                    {
                        txGet.AppendText("Copy " + file1.FileName + " to " + Application.StartupPath);
                        txGet.AppendText("\r\n");

                        PortName = comboPortName.Text;
                        
                        int index = comboBoxDUTSize.SelectedIndex + 1;
                        HexSize = index.ToString();

                        DownloadHexThread = new Thread(new ThreadStart(DownLoadData));
                        DownloadHexThread.IsBackground = true;//设置为后台进程,这样当主线程退出时,这个线程就会退出
                        DownloadHexThread.Start();
                        bDownloadHexThreadOver = false;
                    }
                }
            }
            else
            {
                MessageBox.Show("Before the operation is not over, please wait!", "Waring", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }

        #region 下载hex到编程器
        private void DownLoadData()
        {
            string aug;
            //generate a pacakge code
            Invoke
            (new EventHandler
            (delegate
            {
                txGet.AppendText("\r\n Generate a pacakge code:\r\n");
            }
            )
            );

            //aug = "-g -S 999999 -n "+ file1.FileName + " -r inc\\Aes_Keys.pas -O .\\ -W inc\\temp.txt -l TFP3S -j USB -k " + comboPortName.Text+ " -i \"115200,N,8,1\"";
            aug = "-g -S 999999 -n " + Application.StartupPath + "\\" + HexFileName + " -r " + Application.StartupPath + "\\inc\\Aes_Keys.pas -O .\\ -W " + Application.StartupPath + "\\inc\\temp.txt -l TFP3S -j USB -k " + PortName + " -i \"115200,N,8,1\"";
            proc_execute(aug);
            //FactoryReset
            Invoke
            (new EventHandler
            (delegate
            {
                txGet.AppendText("\r\n FactoryReset:\r\n");
            }
            )
            );

            aug = "-Q -l TFP3S -j USB -k " + PortName + " -i \"115200,N,8,1\"";
            proc_execute(aug);

            //ChangeAESkey
            Invoke
            (new EventHandler
            (delegate
            {
                txGet.AppendText("\r\n ChangeAESkey:\r\n");
            }
            )
            );
            
            aug = "-K -r " + Application.StartupPath + "\\inc\\Aes_Keys.pas -a " + Application.StartupPath + "\\inc\\Aes_Keys_old.pas -l TFP3S -j USB -k " + PortName + " -i \"115200,N,8,1\"";
            proc_execute(aug);

            //SET port to CC51
            Invoke
            (new EventHandler
            (delegate
            {
                txGet.AppendText("\r\n SET port to CC51:\r\n");
            }
            )
            );
            
            aug = "-I 0 -l TFP3S -j USB -k " + PortName + " -i \"115200,N,8,1\"";
            proc_execute(aug);

            //SetDUTsize
            Invoke
            (new EventHandler
            (delegate
            {
                txGet.AppendText("\r\n SetDUTsize:\r\n");
            }
            )
            );

            aug = "-F " + HexSize + " -l TFP3S -j USB -k " + PortName + " -i \"115200,N,8,1\"";
            proc_execute(aug);

            //loadPackageFile
            Invoke
            (new EventHandler
            (delegate
            {
                txGet.AppendText("\r\n LoadPackageFile:\r\n");
            }
            )
            );
            
            aug = "-H -z " + Application.StartupPath + "\\inc\\temp.txt -l TFP3S -j USB -k " + PortName + " -i \"115200,N,8,1\"";
            proc_execute(aug);

            bDownloadHexThreadOver = true;
        }
        #endregion

        private void FormMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            Process[] pProcess;
            pProcess = Process.GetProcesses();
            for (int i = 1; i <= pProcess.Length - 1; i++)
            {
                if (pProcess[i].ProcessName == "TFP3.exe")   //任务管理器应用程序的名
                {
                    pProcess[i].Kill();
                    break;
                }
            }
        }

        //复制一个文件到指定目录
        private static bool CopyFile(string SourcePath, string DestinationPath, bool overwriteexisting, out string FileName)
        {
            bool ret = false;
            FileName = null;
            try
            {
                //SourcePath = SourcePath.EndsWith(@"\") ? SourcePath : SourcePath + @"\";
                DestinationPath = DestinationPath.EndsWith(@"\") ? DestinationPath : DestinationPath + @"\";

                if (Directory.Exists(DestinationPath) == false)
                {
                    Directory.CreateDirectory(DestinationPath);
                }

                FileInfo flinfo = new FileInfo(SourcePath);
                flinfo.CopyTo(DestinationPath + flinfo.Name, overwriteexisting);
                FileName = flinfo.Name;

                ret = true;
            }
            catch (Exception ex)
            {
                ret = false;
            }
            return ret;
        }
    }
}

